
package vectors;

import Exceptions.VectorIndexOutOfBoundsException;
import Exceptions.IncompatibleVectorSizesException;
import java.util.*;


public class ArrayVector implements VectorIn ,Observable  {
      private double[] vector;
      private ArrayList observer;
public ArrayVector (){
    observer = new ArrayList();
}
      
public ArrayVector(int length){
    this.vector = new double[length];
    observer = new ArrayList();
}
public ArrayVector(Double ... e) {
        for (Double elem : e) {
            add(elem);
        observer = new ArrayList();
        }
    }
@Override
public  void setElement(double value, int index){
    if (index < 0 || vector.length < 0)
        throw new VectorIndexOutOfBoundsException();
    this.vector[index] = value;
     elementNotifyObservers(index);
    
} 
      @Override
      public void add(double value){
    double [] temp = new double[vector.length + 1];
    for(int i = 0;i < vector.length; i++){
        temp[i] = vector[i];
     elementNotifyObservers(i);
    }
    temp[temp.length -1 ] = value;
    vector =temp;
     
 }
@Override
public Double getElement(int index){
     if (index < 0 || vector.length < 0)
        throw new VectorIndexOutOfBoundsException();
    return this.vector[index];
} 

@Override
public int getSize(){
    return this.vector.length;
}  

@Override  
public void massiveToVector (double [] massive){  
    for(int i = 0; i < massive.length;i++){
        this.vector[i] = massive[i];
        updateNotifyObservers();
    }
}

@Override
public void objectToVector ( VectorIn Vector1 ){
    for(int i = 0; i < Vector1.getSize(); i++){
        this.vector[i] = Vector1.getElement(i);
    updateNotifyObservers();
    } 
}

public void multiplyVector(double multiply){
    for (int i = 0; i < getSize();i++){
        this.vector[i]*=multiply;   
    updateNotifyObservers();
    }        
}
@Override
public void vectorPlusVector(VectorIn Vector1) throws IncompatibleVectorSizesException{
    if(this.vector.length != Vector1.getSize()){
        throw new IncompatibleVectorSizesException();
    }else{
         for(int i = 0; i < this.vector.length && i <Vector1.getSize(); i++){
           this.vector[i] += Vector1.getElement(i);  
    updateNotifyObservers();
     }
  }
}
@Override
public boolean equalsVectors( VectorIn Vector1){
    boolean f;
    if(this.vector.length != Vector1.getSize() )
          return false;
      for (int i = 0; i < this.vector.length; i++){
          if(this.vector[i] != Vector1.getElement(i))
           return false;
}
          return true;
}
      @Override
public boolean equals(Object obj) {
        if (obj == null)
            return false;
        if (!(obj instanceof VectorIn))
            return false;
        VectorIn vec = (VectorIn) obj;
        if (this.vector.length != vec.getSize())
            return false;

        for (int i = 0; i < this.vector.length; i++) {
            if(getElement(i) != vec.getElement(i))
                return false;
        }

        return true;
    } 
@Override
public String toString(){
StringBuffer str = new StringBuffer();
    for(int i =0 ; i < this.vector.length;i++){
        str.append(this.vector[i]).append("\n");
    }
    return str.toString();
}
      @Override
public int hashCode(){
    int result = 0;
    for(double i : this.vector){
        long bits = Double.doubleToRawLongBits(i);
        result ^=((int)(bits & 0x00000000FFFFFFFFL)) ^ 
                                ((int)((bits & 0xFFFFFFFF00000000L) >> 32));
    }
    return result;
}
@Override
public Object clone()throws CloneNotSupportedException{
    ArrayVector result = null;
        result = (ArrayVector) super.clone();
        result.vector = (double[]) this.vector.clone();
    return result;
}
public Iterator<Double> iterator() {
        return new Iterator<Double>() {
            public int elem = 0;
            @Override
            public void remove() {
            }
            @Override
            public Double next() {
                return getElement(elem++);
            }
            @Override
            public boolean hasNext() {
                if (elem < vector.length)
                    return true;
                else
                    return false;
            }
        };
    }

    @Override
    public void registerObserver(Observer o) {
          observer.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        int i = observer.indexOf(o);
        if (i>=0) 
            observer.remove(i);
    }

    @Override
    public void elementNotifyObservers(int index) {
        for ( int i =0; i< observer.size(); i++)
        {
           Observer observers = (Observer) observer.get(i); 
            observers.updateElement(index);
    }
 }
     
     public void updateNotifyObservers() {
        for ( int i =0; i< observer.size(); i++)
        {
           Observer observers = (Observer) observer.get(i); 
            observers.update();
    }
 }
}